using System.Collections.Generic;
using System.Numerics;
using NUnit.Framework;

namespace ProjectEuler.Core
{
    public class Problem25 : IProjectEulerProblem
    {
        protected KeyValuePair<long, BigInteger> FirstFibonacciTermToContainNumDigits(int num)
        {
            var Fn_2 = new BigInteger(1);
            var Fn_1 = new BigInteger(1);

            var f = Fn_2 + Fn_1;
            long term = 3;
            while (f.ToString().Length < num)
            {
                Fn_2 = Fn_1;
                Fn_1 = f;
                f = Fn_1 + Fn_2;
                term++;
            }
            return new KeyValuePair<long, BigInteger>(term, f);
        }

        public int Number
        {
            get { return 25; }
        }

        public string Description
        {
            get { return "What is the first term in the Fibonacci sequence to contain 1000 digits?"; }
        }

        public string Answer
        {
            get
            {
                var pair = FirstFibonacciTermToContainNumDigits(1000);
                return "F_" + pair.Key + " => " + pair.Value;
            }
        }
    }

    [TestFixture]
    public class Problem25Tests : Problem25
    {
        [Test]
        public void The_first_term_to_contain_3_digits_is_144_the_12th_term()
        {
            var pair = FirstFibonacciTermToContainNumDigits(3);
            Assert.AreEqual(pair.Key, 12);
            Assert.AreEqual(pair.Value, new BigInteger(144));
        }

        [Test]
        public void The_first_term_to_contain_4_digits_is_1597_the_17th_term()
        {
            var pair = FirstFibonacciTermToContainNumDigits(4);
            Assert.AreEqual(pair.Key, 17);
            Assert.AreEqual(pair.Value, new BigInteger(1597));
        }

        [Test]
        public void The_first_term_to_contain_5_digits_is_10946_the_21st_term()
        {
            var pair = FirstFibonacciTermToContainNumDigits(5);
            Assert.AreEqual(pair.Key, 21);
            Assert.AreEqual(pair.Value, new BigInteger(10946));
        }

    }
}